<template>
  <!-- 查询区域 -->
  <div style="">
    <a-modal v-model:open="deleteOpen" title="删除提示" ok-text="确认" cancel-text="取消" @ok="deleteOk">
      确认删除？
    </a-modal>
    <a-modal v-model:open="addOpen" v-model:title="addModifyTitle" :footer="null" :afterClose="afterCloseModal">
      <!---->
      <a-form ref="formRef" :model="user" :label-col="labelCol" :wrapper-col="wrapperCol" :rules="userRules"
        @finish="onFinish" @finishFailed="onFinishFailed">
        <input type="hidden" name="id" v-model="user.id" />
        <a-form-item label="账号" name="username">
          <!--修改用户时,账号不能修改-->
          <a-input v-if="disabledFlag" v-model:value="user.username" disabled />
          <a-input v-else v-model:value="user.username" />
        </a-form-item>
        <a-form-item label="姓名" name="name">
          <a-input v-model:value="user.name" />
        </a-form-item>
        <a-form-item label="邮箱" name="email">
          <a-input v-model:value="user.email" />
        </a-form-item>
        <a-form-item label="手机" name="mobile">
          <a-input v-model:value="user.mobile" />
        </a-form-item>
        <a-form-item label="是否激活">
          <a-switch v-model:checked="user.enabled" name="enabled" />
        </a-form-item>
        <a-form-item label="账号过期">
          <a-switch v-model:checked="user.accountNonExpired" name="accountNonExpired" />
        </a-form-item>
        <a-form-item label="账号锁定">
          <a-switch v-model:checked="user.accountNonLocked" name="accountNonLocked" />
        </a-form-item>
        <a-form-item label="密码过期">
          <a-switch v-model:checked="user.credentialsNonExpired" name="credentialsNonExpired" />
        </a-form-item>
        <a-form-item :wrapper-col="{ span: 14, offset: 4 }">
          <a-button type="primary" html-type="submit">保存</a-button>
          <a-button style="margin-left: 10px" @click="closeForm">关闭</a-button>
        </a-form-item>
      </a-form>
    </a-modal>

    <a-modal v-model:open="roleOpen" title="设置用户角色" @ok="handleAttachRoleOk">
      <a-table bordered class="ant-table-striped"
        :row-class-name="(_record: any, index: any) => (index % 2 === 1 ? 'table-striped' : null)" :columns="roleColumns"
        :loading="loading" :rowSelection="{ selectedRowKeys: roleSelectedRowKeys, onChange: onRoleSelectChange }"
        :dataSource="roleTabledata" :pagination="roleIpagination" :scroll="{}" :customRow="roleRowClick"
        @change="handleRoleTableChange">

      </a-table>
    </a-modal>

    <a-row>
      <a-col :span="24">
        <a-form layout="inline">
          <a-form-item label="姓名">
            <a-input placeholder="输入姓名模糊查询" v-model:value="queryParam.name" />
          </a-form-item>
          <a-form-item label="手机号">
            <a-input placeholder="输入手机号模糊查询" v-model:value="queryParam.mobile" />
          </a-form-item>
          <a-space wrap>
            <a-button type="primary" @click="searchQuery">查询</a-button>
            <a-button type="primary" @click="searchReset">重置</a-button>
          </a-space>
        </a-form>
      </a-col>
    </a-row>
  </div>

  <!-- 操作按钮区域 -->

  <div class="table-operator" style="margin:5px 0;border-top: 5px;float: left; ">
    <a-space wrap>
      <a-button @click="handleAdd" type="primary">添加用户</a-button>
      <a-button @click="handleModify" type="primary">修改用户</a-button>
      <a-button @click="handleDelete" type="primary">删除用户</a-button>
      <a-button @click="attachRole" type="primary">配置角色</a-button>
    </a-space>
  </div>
  <div style="margin:5px 0;padding:5px 0;">
    <a-table bordered class="ant-table-striped"
      :row-class-name="(_record: any, index: any) => (index % 2 === 1 ? 'table-striped' : null)" :columns="columns"
      :loading="loading" :rowSelection="{ selectedRowKeys, onChange: onSelectChange }" :dataSource="tabledata"
      :pagination="ipagination" :scroll="{}" :customRow="rowClick" @change="handleTableChange">
      <template #bodyCell="{ column, record }">
        <template v-if="column.dataIndex === 'enabled'">
          <span v-if="record.enabled">
            是
          </span>
          <span v-else>
            否
          </span>
        </template>

        <template v-if="column.dataIndex === 'accountNonExpired'">
          <span v-if="record.accountNonExpired">
            未过期
          </span>
          <span v-else>
            已过期
          </span>
        </template>
        <template v-if="column.dataIndex === 'accountNonLocked'">
          <span v-if="record.accountNonLocked">
            未锁定
          </span>
          <span v-else>
            已锁定
          </span>
        </template>
        <template v-if="column.dataIndex === 'credentialsNonExpired'">
          <span v-if="record.credentialsNonExpired">
            未过期
          </span>
          <span v-else>
            已过期
          </span>
        </template>
      </template>
    </a-table>
  </div>
</template>
 
<script lang="ts" setup>
import {
  ref,
  reactive,
  onMounted,
  Ref
} from "vue";
import type { UnwrapRef } from 'vue';
import { message, Form } from 'ant-design-vue';
import http from '@/utils/http';
import showErrors from '@/utils/publicfunction';
import type { Data } from '@/utils/http';
import * as _ from 'lodash';


/**
 * 用户对象数据类型定义
 * id 
 * name 姓名
 * username 账号
 * email 邮箱
 * mobile 手机
 * enabled 是否激活，默认激活
 * accountNonExpired 账户是否未过期，默认未过期
 * accountNonLocked  账户是否未锁定，默认未锁定
 * credentialsNonExpired 密码是否未过期，默认未过期
 */
interface FormState {
  id: number;
  name: string;
  username: string;
  email: string;
  mobile: string;
  enabled: boolean;
  accountNonExpired: boolean;
  accountNonLocked: boolean;
  credentialsNonExpired: boolean;
}

//列表数据类型定义
interface ColumnProp extends FormState {
  key: number;
}
//分页组件
interface PaginationProp {
  current: number;
  pageSize: number;
  total: number;
  showSizeChanger: boolean;
  showQuickJumper: boolean;
  pageSizeOptions: string[];
  showTotal: (total: number, range: number[]) => string;
}

//列表数据变量定义
const tabledata: Ref<ColumnProp[]> = ref([]);
//列表的表头定义
const columns = [
  { title: "账号", dataIndex: "username" },
  { title: "姓名", dataIndex: "name" },
  { title: "邮箱", dataIndex: "email" },
  { title: "手机", dataIndex: "mobile" },
  { title: "是否激活", dataIndex: "enabled" },
  { title: "账号过期", dataIndex: "accountNonExpired" },
  { title: "账号锁定", dataIndex: "accountNonLocked" },
  { title: "密码过期", dataIndex: "credentialsNonExpired" },
];

const loading = ref(false);
//查询参数定义
const queryParam = reactive({
  name: "",
  mobile: ""
});

//列表选择的数据的key列表
const selectedRowKeys: Ref<number[]> = ref([]);
//列表选择的数据整行值列表
let selectionRows: ColumnProp[] = [];

//行点击事件,record参数为该行的整行值
const rowClick = (record: ColumnProp, index: number) => {
  return {
    //单击事件
    onClick: (event: MouseEvent) => {
      // const computedSelectedRowKeys = computed(() => selectedRowKeys.value)
      //   .value;
      //如果该行已经被选择，取消选择
      if (selectedRowKeys.value.includes(record.id)) {
        //过滤掉该行的key
        selectedRowKeys.value = selectedRowKeys.value.filter(function (
          val,
          index,
          arr
        ) {
          return val != record.id;
        });
        //过滤掉该行的数据整行值
        selectionRows = selectionRows.filter(function (
          val,
          index,
          arr
        ) {
          return val.id != record.id;
        });
      } else {
        //如果该行没有被选择，则进行选择，selectedRowKeys是响应数据，添加数据就是选择了行
        selectedRowKeys.value.push(record.id);
        //选择的数据整行值
        selectionRows.push(record);
        // console.log('push length'+selectionRows.value.length)
      }
    }
  };
};
//分页栏定义
const ipagination: Ref<PaginationProp> = ref({
  //hideOnSinglePage:true,//只有一页时是否隐藏分页器
  current: 0,
  pageSize: 8,
  total: 0,
  showSizeChanger: true,
  showQuickJumper: true,
  pageSizeOptions: ["8", "10", "20"], //这里注意只能是字符串，不能是数字
  showTotal: (total: number, range: number[]) =>
    `显示${range[0]}-${range[1]}条，共有 ${total}条`,
});
// const generateData = (n: number, pageSize: number) => {
//   const result: ColumnProp[] = [];
//   for (let i = 0; i < pageSize; i++) {
//     result.push({
//       key: i + pageSize * n,
//       idcard: i + pageSize * n,
//       name: `Edward King ${i + pageSize * n}`,
//       age: 32,
//       sex: i % 2,
//       mobile: "13555555",
//     });
//   }
//   return result;
// };

//执行查询公用方法
const executeQuery = (pageParam: Data) => {
  loading.value = true;

  http.get('/user/page', pageParam).then((res) => {
    loading.value = false;
    if (res.data.status === "success") {
      tabledata.value = res.data.businessData.pageData;
      ipagination.value.total = res.data.businessData.total;
    }
    else {
      message.error(res.data.businessData.errMsg);
    }
  })
  //重置key值的数组
  selectedRowKeys.value = [];
  //重置选择的数据值的数组
  selectionRows = [];
}
//查询按钮事件
const searchQuery = () => {
  ipagination.value.current = 1;
  const pageParam = {
    pageNo: 0,
    pageSize: ipagination.value.pageSize,
    name: queryParam.name,
    mobile: queryParam.mobile

  }
  //执行查询公用方法
  executeQuery(pageParam);
};
//重置按钮事件
const searchReset = () => {
  queryParam.mobile = "";
  queryParam.name = "";
};


//点击每列左边的checkbox后的事件
const onSelectChange = (
  pselectedRowKeys: number[],
  pselectionRows: ColumnProp[]
) => {
  selectedRowKeys.value = pselectedRowKeys;
  selectionRows = pselectionRows;
};

//页码改变的回调，参数是改变后的页码及每页条数
const handleTableChange = (
  pagination: PaginationProp,
  filters: any,
  sorter: any
) => {
  //页码改变的回调，参数是改变后的页码及每页条数
  // console.log(pagination)
  // console.log(filters)
  // console.log(sorter)
  ipagination.value.current = pagination.current;
  const pageParam = {
    pageNo: ipagination.value.current - 1,
    pageSize: ipagination.value.pageSize,
    name: queryParam.name,
    mobile: queryParam.mobile
  }
  //执行查询公用方法
  executeQuery(pageParam);
};



/******新增用户*********/

//用户对象数据变量定义
const user: UnwrapRef<FormState> = reactive({
  id: 0,
  name: "",
  username: "",
  email: "",
  mobile: "",
  enabled: true,
  accountNonExpired: true,
  accountNonLocked: true,
  credentialsNonExpired: true
});

//form的校验规则
const userRules = {
  name: [
    {
      required: true,
      message: "用户名为必填项！",
      trigger: "blur",
    },
    {
      max: 20,
      message: "用户名长度不得超过20！",
      trigger: "blur",
    },
  ],
  username: [
    {
      required: true,
      message: "用户账号为必填项！",
      trigger: "blur",
    },
    {
      max: 20,
      message: "用户账号长度不得超过20！",
      trigger: "blur",
    },
    {
      // 异步验证 多了一个callback函数
      validator: (rule: any, val: any, callback: any) => {

        if (val.length > 0) {
          const usernameParam = {
            username: val,
            id: user.id
          };
          // 这里进行异步操作,下面以promise举例
          http.get('/user/validateUsername', usernameParam).then((res) => {
            if (res.data.status === "success") {
              callback()
            }
            else {
              callback(new Error('用户账号不能重复'))
            }
          })
        } else {
          callback()
        }
      },
      trigger: "blur"
    }
  ],
  email: [
    {
      required: true,
      message: "邮箱为必填项！",
      trigger: "blur",
    },
    {
      pattern: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/,
      message: '邮箱格式不正确',
      trigger: "blur",
    },
    {
      // 异步验证 多了一个callback函数
      validator: (rule: any, val: any, callback: any) => {

        if (val.length > 0) {
          const emailParam = {
            email: val,
            id: user.id
          };
          // 这里进行异步操作,下面以promise举例
          http.get('/user/validateEmail', emailParam).then((res) => {
            if (res.data.status === "success") {
              callback()
            }
            else {
              callback(new Error('邮箱不能重复'))
            }
          })
        } else {
          callback()
        }
      },
      trigger: "blur"
    }
  ],
  mobile: [
    {
      required: true,
      message: "手机为必填项！",
      trigger: "blur",
    },
    {
      pattern: /^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/,
      message: '请输入正确手机号',
      trigger: "blur",
    },
    {
      // 异步验证 多了一个callback函数
      validator: (rule: any, val: any, callback: any) => {

        if (val.length > 0) {
          const mobileParam = {
            mobile: val,
            id: user.id
          };
          // 这里进行异步操作,下面以promise举例
          http.get('/user/validateMobile', mobileParam).then((res) => {
            if (res.data.status === "success") {
              callback()
            }
            else {
              callback(new Error('手机号码不能重复'))
            }
          })
        } else {
          callback()
        }
      },
      trigger: "blur"
    }
  ]
};

//重置用户对象数据
const clearUser = () => {
  user.id = 0;
  user.name = "";
  user.username = "";
  user.email = "";
  user.mobile = "";
  user.enabled = true;
  user.accountNonExpired = true;
  user.accountNonLocked = true;
  user.credentialsNonExpired = true;
};
//设置用户对象数据
const setUser = () => {
  user.id = selectionRows[0].id;
  user.name = selectionRows[0].name;
  user.username = selectionRows[0].username;
  user.email = selectionRows[0].email;
  user.mobile = selectionRows[0].mobile;
  user.enabled = selectionRows[0].enabled;
  user.accountNonExpired = selectionRows[0].accountNonExpired;
  user.accountNonLocked = selectionRows[0].accountNonLocked;
  user.credentialsNonExpired = selectionRows[0].credentialsNonExpired;
};
//form中label宽度
const labelCol = { style: { width: '150px' } };
const wrapperCol = { span: 14 };
//打开或关闭用户form窗口
const addOpen = ref<boolean>(false);
//窗口title
const addModifyTitle = ref<string>("新增用户");
//是否改动用户账号，新增时可修改，修改用户数据时，账号不能修改
const disabledFlag = ref<boolean>(false);
const formRef = ref();

//关闭窗口
const closeForm = () => {
  //关闭窗口
  addOpen.value = false;
}

//窗口关闭后清除校验信息
const afterCloseModal = () => {
  formRef.value.clearValidate();
}

//新增用户按钮点击事件
const handleAdd = () => {
  //重置用户数据
  clearUser();
  //修改title
  addModifyTitle.value = "新增用户";
  //新增可以修改账号
  disabledFlag.value = false;
  //打开窗口
  addOpen.value = true;

};


//校验成功后提交form
const onFinish = (values: any) => {
  let url = '/user/addUser';
  //如果id不为0，则为修改数据，走修改数据的url
  if (user.id != 0) {
    url = '/user/modifyUser';
  }
  http.post(url, user).then((res) => {
    if (res.data.status === "success") {
      message.success("保存成功!");
      //关闭窗口
      addOpen.value = false;

      //刷新列表
      const pageParam = {
        pageNo: ipagination.value.current - 1,
        pageSize: ipagination.value.pageSize,
        name: queryParam.name,
        mobile: queryParam.mobile
      }
      //执行查询公用方法
      executeQuery(pageParam);
    }
    else {
        showErrors(res.data.businessData);
    }
  })

};

const onFinishFailed = (errorInfo: any) => {
  console.log('Failed:', errorInfo);
};
/******新增用户结束*********/

/******修改用户*********/
//修改按钮点击事件
const handleModify = () => {
  //如果选择了一条数据
  if (selectionRows.length == 1) {
    //设置用户数据
    setUser();
    //设置窗口title
    addModifyTitle.value = "修改用户";
    //账号不可修改
    disabledFlag.value = true;

    //打开窗口
    addOpen.value = true;
  } else {
    message.info("请选择一条数据!");
  }
};
/******修改用户结束*********/

/******删除用户*********/
//删除提示框显示变量
const deleteOpen = ref<boolean>(false);
//删除按钮点击事件
const handleDelete = () => {
  //判断是否选择了数据
  if (selectedRowKeys.value.length == 0) {
    message.info("请选择数据");
    return;
  }
  //显示删除数据提示框
  deleteOpen.value = true;
};

//确定删除
const deleteOk = () => {
  //关闭提示框
  deleteOpen.value = false;
  // //要删除的数据参数
  // const deleteParam = {
  //   params: {
  //     ids: selectedRowKeys.value
  //   }
  // }

  //删除
  http.delete('/user/delete', selectedRowKeys.value).then((res) => {
    if (res.data.status === "success") {
      //刷新列表
      const pageParam = {
        pageNo: ipagination.value.current - 1,
        pageSize: ipagination.value.pageSize,
        name: queryParam.name,
        mobile: queryParam.mobile
      }
      //执行查询公用方法
      executeQuery(pageParam);
    }
    else {
      message.error(res.data.businessData.errMsg);
    }
  })
};
/******删除用户结束*********/

/******设置角色*********/

/**
 * 列表数据类型定义
 * key table组件需要
 * id
 * authority 角色名称，有唯一约束，不能重复 ROLE_USER  ROLE_ADMIN等
 * displayName 角色显示名称 普通用户，管理员等
 */
interface RoleColumnProp {
  key: number;
  id: number;
  authority: string;
  displayName: string;
}

//列表数据变量定义
const roleTabledata: Ref<RoleColumnProp[]> = ref([]);
//列表的表头定义
const roleColumns = [
  { title: "角色名称", dataIndex: "authority" },
  { title: "角色显示名称", dataIndex: "displayName" }
];


//列表选择的数据的key列表
const roleSelectedRowKeys: Ref<number[]> = ref([]);
const roleOpen = ref<boolean>(false);
//当前页已经被设置过的roleid
let oldData: number[] = [];
//行点击事件,record参数为该行的整行值
const roleRowClick = (record: RoleColumnProp, index: number) => {
  return {
    //单击事件
    onClick: (event: MouseEvent) => {
      //如果该行已经被选择，取消选择
      if (roleSelectedRowKeys.value.includes(record.id)) {
        //过滤掉该行的key
        roleSelectedRowKeys.value = roleSelectedRowKeys.value.filter(function (
          val,
          index,
          arr
        ) {
          return val != record.id;
        });
      } else {
        //如果该行没有被选择，则进行选择，selectedRowKeys是响应数据，添加数据就是选择了行
        roleSelectedRowKeys.value.push(record.id);
        // console.log('push length'+selectionRows.value.length)
      }
    }
  };
};
//分页栏定义
const roleIpagination: Ref<PaginationProp> = ref({
  //hideOnSinglePage:true,//只有一页时是否隐藏分页器
  current: 0,
  pageSize: 5,
  total: 0,
  showSizeChanger: true,
  showQuickJumper: true,
  pageSizeOptions: ["5", "10", "20"], //这里注意只能是字符串，不能是数字
  showTotal: (total: number, range: number[]) =>
    `显示${range[0]}-${range[1]}条，共有 ${total}条`,
});

//执行查询公用方法
const executeQueryRole = (pageParam: Data) => {
  loading.value = true;

  http.get('/user/rolePage', pageParam).then((res) => {
    loading.value = false;
    if (res.data.status === "success") {
      roleTabledata.value = res.data.businessData.pageData;
      roleIpagination.value.total = res.data.businessData.total;
      //设置key值的数组
      roleSelectedRowKeys.value = res.data.businessData.checkedList;
      //当前页已经被设置过的roleid
      oldData = _.clone(res.data.businessData.checkedList);
    }
    else {
      message.error(res.data.businessData.errMsg);
    }
  })
}

//设置完成后点击确定事件
const handleAttachRoleOk = (
) => {
  const dl = roleSelectedRowKeys.value.length;
  const addData = [];
  const delData = [];
  const odl = oldData.length;
  // console.log("roleSelectedRowKeys.value--------------------")
  // console.log(roleSelectedRowKeys.value)
  // console.log("oldData-------------------")
  // console.log(oldData)
  let j = 0;
  // 新增数据
  for (let i = 0; i < dl; i++) {
    j = 0;
    for (; j < odl; j++) {
      if (roleSelectedRowKeys.value[i] == oldData[j]) {
        break;
      }
    }
    if (j == odl) {
      addData.push(roleSelectedRowKeys.value[i]);
    }
  }
  // 删除数据
  for (let i = 0; i < odl; i++) {
    j = 0;
    for (; j < dl; j++) {
      if (oldData[i] == roleSelectedRowKeys.value[j]) {
        break;
      }
    }
    if (j == dl) {
      delData.push(oldData[i]);
    }
  }

  if (addData.length > 0 || delData.length > 0) {
    // console.log("addData------------------")
    //     console.log(addData)
    //     console.log("delData------------------")
    //     console.log(delData)
    //要设置的用户角色参数
    const roleParam = {
      params: {
        addData,
        delData,
        userId: selectedRowKeys.value[0]
      }
    }

    //设置
    http.post('/user/attachRoleToUser', {}, roleParam).then((res) => {
      if (res.data.status === "success") {
        message.success("设置角色成功");
        roleOpen.value = false;
      }
      else {
        message.error(res.data.businessData.errMsg);
      }
    })

  } else {
    roleOpen.value = false;
  }
};
//点击每列左边的checkbox后的事件
const onRoleSelectChange = (
  pselectedRowKeys: number[],
  pselectionRows: RoleColumnProp[]
) => {
  roleSelectedRowKeys.value = pselectedRowKeys;
};

//页码改变的回调，参数是改变后的页码及每页条数
const handleRoleTableChange = (
  pagination: PaginationProp,
  filters: any,
  sorter: any
) => {
  //页码改变的回调，参数是改变后的页码及每页条数
  // console.log(pagination)
  // console.log(filters)
  // console.log(sorter)
  roleIpagination.value.current = pagination.current;
  const pageParam = {
    pageNo: roleIpagination.value.current - 1,
    pageSize: roleIpagination.value.pageSize,
    userId: selectedRowKeys.value[0]
  }
  //执行查询公用方法
  executeQueryRole(pageParam);
};

//配置角色按钮点击事件
const attachRole = () => {
  //如果选择了一条数据
  if (selectionRows.length == 1) {
    //打开窗口
    roleOpen.value = true;
    roleIpagination.value.current = 1;
    const pageParam = {
      pageNo: 0,
      pageSize: roleIpagination.value.pageSize,
      userId: selectedRowKeys.value[0]
    }
    //执行查询公用方法
    executeQueryRole(pageParam);
  } else {
    message.info("请选择一条数据!");
  }
}
/******设置角色结束*********/

//页面加载完成后，刷新第一页数据
onMounted(() => {
  //如果table设置了 :scroll="{ x: 1500 }"，则要先给个数据，否则报错
  tabledata.value = [{
    "id": 1,
    "username": "user",
    "mobile": "13012341234",
    "name": "Zhang San",
    "enabled": true,
    "accountNonExpired": true,
    "accountNonLocked": true,
    "credentialsNonExpired": true,
    "email": "zhangsan@local.dev",
    "key": 1
  }];
  tabledata.value = [];
  ipagination.value.current = 1;
  const pageParam = {
    pageNo: 0,
    pageSize: ipagination.value.pageSize,
    name: "",
    mobile: ""
  }
  //执行查询公用方法
  executeQuery(pageParam);
});

</script>
<style scoped>
/*[data-doc-theme='light'] */
.ant-table-striped :deep(.table-striped) td {
  background-color: #fafafa;
}

[data-doc-theme='dark'] .ant-table-striped :deep(.table-striped) td {
  background-color: rgb(29, 29, 29);
}
</style>